package com.freejava.test_websocket.component;

import com.alibaba.fastjson.JSON;
import com.freejava.test_websocket.chatobject.Message;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/chat")
public class WebSocketChatServer {

    /**
     * 使用线程安全的Map存储会话。
     */
    private static Map<String, Session> onlineSessions = new ConcurrentHashMap<>();


    /**
     * 当打开连接的时候，添加会话和更新在线人数。
     */
    @OnOpen
    public void onOpen(Session session) {
        onlineSessions.put(session.getId(), session);
        sendMessageToAll(Message.toJsonResult(Message.ENTER, "", "", onlineSessions.size()));
    }

    /**
     * 当客户端发送消息,群发该消息，消息使用json格式。
     */
    @OnMessage
    public void onMessage(Session session, String jsonStr) {
        Message message = JSON.parseObject(jsonStr, Message.class);
        sendMessageToAll(Message.toJsonResult(Message.TALK, message.getUsername(), message.getMessage(), onlineSessions.size()));
    }

    /**
     * 当关闭连接，移除会话并减少在线人数。
     */
    @OnClose
    public void onClose(Session session) {
        onlineSessions.remove(session.getId());
        sendMessageToAll(Message.toJsonResult(Message.QUIT, "", "下线啦！", onlineSessions.size()));
    }

    /**
     * 处理信发生异常
     */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    /**
     * 发送信息给所有人
     */
    private static void sendMessageToAll(String msg) {
        onlineSessions.forEach((id, session) -> {
            try {
                session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 系统消息推送，一般是有人来去
     *
     * @param msg
     */
    private static void noticeMessage(String msg) {
        sendMessageToAll(Message.toJsonResult(Message.TALK, "系统消息", msg, onlineSessions.size()));
    }

}
